-
Notifications
You must be signed in to change notification settings - Fork 184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make TLS verification of upstream servers configurable #49
Conversation
f6edec7
to
a6a87fa
Compare
a6a87fa
to
e4679d6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for opening @sporkmonger, some initial requests!
internal/proxy/proxy_config.go
Outdated
@@ -48,6 +48,7 @@ type UpstreamConfig struct { | |||
|
|||
SkipAuthCompiledRegex []*regexp.Regexp | |||
AllowedGroups []string | |||
TLSVerify bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like in this case, the default for TLSVerify
would be false, which would be a less secure default. Can you change this field to be InsecureSkipVerify
, which when set to true, will enable InsecureSkipVerify
? This will allow us to default to a more secure configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, and agree that default should be to verify. I meant to address that and forgot. However InsecureSkipVerify
is a good name only inside a config struct named TLSConfig
. It's not obvious that it's even TLS related outside that context. Given that, I'd be inclined to explicitly set a default rather than relying on zero values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we make the name TLSSkipVerify
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Main reason I'd choose TLSVerify
over TLSSkipVerify
is that TLSVerify
/ TLS_VERIFY
/ --tls-verify
and similar are in wide usage in other tools, whereas TLSSkipVerify
would be relatively uncommon. I also generally don't like to let language details (like what Go's zero values are) to leak out into user-facing interface design, and I think of config as part of the interface design.
"--tls-verify": 23,400 search results
"TLSVerify": 12,800 search results
"--tls-skip-verify": 2,210 search results
"TLSSkipVerify": 1,600 search results
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That said, there's certainly other tools using TLSSkipVerify
, like Vault and KSonnet, so it's not without precedent. Funny how it seems to be mostly prevalent in Go apps. 😛
internal/proxy/proxy_config.go
Outdated
@@ -75,6 +76,7 @@ type OptionsConfig struct { | |||
HeaderOverrides map[string]string `yaml:"header_overrides"` | |||
SkipAuthRegex []string `yaml:"skip_auth_regex"` | |||
AllowedGroups []string `yaml:"allowed_groups"` | |||
TLSVerify bool `yaml:"tls_verify"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nit) Can we add a unit test for this config value to ensure that it is being set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely. I was having trouble understanding the test suite when I first wrote the PR, but a couple PRs in, I think it should be no problem.
a0b0d5b
to
5c24ded
Compare
Added tests for TLS verification, wanted to make sure everyone's OK w/ keeping the |
5c24ded
to
9a1a35f
Compare
Ended up writing the code for it because it turned out to be easier than I thought it would be, but it's super easy to switch if you do prefer |
internal/proxy/proxy_config.go
Outdated
proxy.TLSVerify = proxy.RouteConfig.Options.TLSVerify | ||
if proxy.RouteConfig.Options.TLSVerify != nil { | ||
proxy.TLSVerify = *proxy.RouteConfig.Options.TLSVerify | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One item of note, we don't want to set the explicit default value here because of the if proxy.RouteConfig.Options == nil
short-circuit at the top of the function. Doing so causes half the test suite to fail. I put it in loadServiceConfigs
instead.
internal/proxy/proxy_config.go
Outdated
@@ -75,6 +76,7 @@ type OptionsConfig struct { | |||
HeaderOverrides map[string]string `yaml:"header_overrides"` | |||
SkipAuthRegex []string `yaml:"skip_auth_regex"` | |||
AllowedGroups []string `yaml:"allowed_groups"` | |||
TLSVerify *bool `yaml:"tls_verify"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it still makes sense to use TLSSkipVerify
as a bool
, which removes the need for any default setting on load of the service configs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I'll change it.
f311a8f
to
3eca28c
Compare
OK, it's been switched to |
3eca28c
to
735ed1f
Compare
internal/proxy/oauthproxy_test.go
Outdated
@@ -201,6 +201,110 @@ func TestNewReverseProxyHostname(t *testing.T) { | |||
|
|||
} | |||
|
|||
func TestNewReverseProxyTLSSkipVerifyFalse(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While some of our tests in this file are not, we are trying to standardize on writing table driven tests in our codebase, could you consolidate these two tests into one function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer table driven tests, was just mirroring what was already there. Happy to convert over.
735ed1f
to
9440668
Compare
Does it make it easier to review if I squash earlier in the PR or at the end? |
At the end would be easier, thanks for asking, this also looks good to me if you'd like to rebase + squash, we can get this merged! |
e2eed96
to
780b504
Compare
All rebased and squashed! |
internal/proxy/oauthproxy.go
Outdated
|
||
// RoundTrip round trips the request and deletes security headers before returning the response. | ||
func (t *upstreamTransport) RoundTrip(req *http.Request) (*http.Response, error) { | ||
resp, err := http.DefaultTransport.RoundTrip(req) | ||
transport := &http.Transport{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than creating a new transport every time, can we make this initialize one once and reuse it instead? This will hopefully reduce the overhead of TCP connections made.
Added one more request! |
No worries! Downside is it's a little more repetitious this way, but because of the shape of the structure and pointers, it's a little more challenging to factor that out in a way that wouldn't be buggy. Open to ideas. |
internal/proxy/oauthproxy.go
Outdated
@@ -167,7 +154,21 @@ func (t *upstreamTransport) RoundTrip(req *http.Request) (*http.Response, error) | |||
// It adds an X-Forwarded-Host header that is the request's host. | |||
func NewReverseProxy(to *url.URL, config *UpstreamConfig) *httputil.ReverseProxy { | |||
proxy := httputil.NewSingleHostReverseProxy(to) | |||
proxy.Transport = &upstreamTransport{InsecureSkipVerify: config.TLSSkipVerify} | |||
proxy.Transport = &upstreamTransport{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: we can probably create a function that initializes the upstreamTransport{}
, something like NewUpstreamTransport(insecureSkipVerify bool)
so that we're not repeating the config code twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I like that solution better.
OK, I think this should be ready to go. Squash again? |
d3801cf
to
3a839e6
Compare
Thanks for the help getting the PR cleaned up! |
Beautiful. Ive already been using this prior to the merge. Thanks @sporkmonger |
When pointing the proxy directly at an AWS ALB, e.g., the cert presented by the ALB is guaranteed to be invalid, as you can't get a cert for
*.elb.amazonaws.com
. Depending on your deployment setup you may or may not be able to easily automate creation of corresponding DNS records to match your certs. And of course your certs might be self-signed. Therefore it's desirable to be able to disable TLS verification for upstream servers in some cases. Particularly because the real security barrier is the necessary firewall rule that ensures nothing else can talk to the upstream server.Fixes #47.